package cn.com.zcode.auth.control;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.struts2.json.JSONException;
import org.apache.struts2.json.JSONUtil;

import cn.com.zcode.auth.model.Resource;
import cn.com.zcode.auth.model.UserRole;
import cn.com.zcode.auth.model.UserToken;
import cn.com.zcode.auth.service.AuthService;
import cn.com.zcode.user.model.LoginInfo;
import cn.com.zcode.user.model.User;
import cn.com.zcode.user.service.UserService;

public class ShiroDataBaseRealm extends AuthorizingRealm {

	private static Logger logger = Logger.getLogger(ShiroDataBaseRealm.class);
	private UserService userService;

	private AuthService authService;

	/**
	 * 
	 * 当用户进行访问链接时的授权方法
	 * 
	 */
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		logger.info("===========Authorization===========");
		Subject subject = SecurityUtils.getSubject();
		Session session = subject.getSession();
		User user = (User) session.getAttribute(User.SESSION_USER);
		List<UserRole> roles = authService.findRoles(user.getId());
		Set<String> roleList = new HashSet<String>();
		Set<String> permissionList = new HashSet<String>();

		for (UserRole role : roles) {
			String rolename = role.getRoleName();
			roleList.add(rolename);
			Set<Resource> res = role.getResources();
			for (Resource resource : res) {
				String code = resource.getCode();
				permissionList.add(code);

			}

		}

		SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
		simpleAuthorInfo.addRoles(roleList);
		simpleAuthorInfo.addStringPermissions(permissionList);
		return simpleAuthorInfo;

	}

	/**
	 * 用户登录的认证方法
	 * 
	 */
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		logger.info("===========LOGIN Authentication===========");
		UserToken usertoken = (UserToken) token;
		String username = usertoken.getUsername();
		logger.debug("验证当前Subject时获取到token为:" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));
		User user = this.userService.getUserByName(username);
		if (user != null) {
			try {
				Subject subject = SecurityUtils.getSubject();
				Session session = subject.getSession();
				String password = user.getPasswordMD5();
				String name = this.getName();
				String ip = usertoken.getIp();
				boolean isFromMobile = usertoken.isFromMobile();
				AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(username, password, name);
				user.setFromMobile(isFromMobile);
				user.setIp(ip);
				session.setAttribute(User.SESSION_USER, user);
				session.setAttribute(User.SESSION_USER_JSON, JSONUtil.serialize(user));
				LoginInfo logininfo = new LoginInfo(user, ip);
				userService.addLoginInfo(logininfo);
				return authcInfo;
			} catch (JSONException e) {
				e.printStackTrace();
				logger.error(e);
			}
		} else {
			throw new UnknownAccountException("用户不存在");
		}
		return null;

	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public AuthService getAuthService() {
		return authService;
	}

	public void setAuthService(AuthService authService) {
		this.authService = authService;
	}

}